/*
 * GraphNode.h
 *
 *  Created on: 14/11/2011
 *      Author: will
 */

#ifndef GRAPHNODE_H_
#define GRAPHNODE_H_

#include <vector>
#include <utility>
#include <eigen3/Eigen/Core>
#include <opencv2/opencv.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/utility.hpp>
#include "mex.h"

#include "GraphEdge.h"
#include "../bagofwords/BagOfWords.h"

using std::vector;
using std::pair;
using Eigen::Vector3d;
using Eigen::Matrix3d;
using cv::Mat;

/*
BOOST_SERIALIZATION_SPLIT_FREE(::cv::Mat)
namespace boost {
namespace serialization {
/** Serialization support for cv::Mat */ /*
template <class Archive>
void save(Archive & ar, const ::cv::Mat& m, const unsigned int version) {
	size_t elem_size = m.elemSize();
	size_t elem_type = m.type();

	ar & m.cols;
	ar & m.rows;
	ar & elem_size;
	ar & elem_type;

	const size_t data_size = m.cols * m.rows * elem_size;
	ar & boost::serialization::make_array(m.ptr(), data_size);
}

/** Serialization support for cv::Mat */ /*
template <class Archive>
void load(Archive & ar, ::cv::Mat& m, const unsigned int version) {
	int cols, rows;
	size_t elem_size, elem_type;

	ar & cols;
	ar & rows;
	ar & elem_size;
	ar & elem_type;

	m.create(rows, cols, elem_type);

	size_t data_size = m.cols * m.rows * elem_size;
	ar & boost::serialization::make_array(m.ptr(), data_size);
}
}
}
*/

class GraphEdge;

class GraphNode {
public:
	GraphNode();
	virtual ~GraphNode();
	GraphNode(const GraphNode & other);
	GraphNode & operator=(const GraphNode & other);

	// Location Data
	unsigned int frameNum;
	Vector3d position;
	Mat* descriptors;
	Bagofwords* bagOfWords;
	vector<GraphEdge*> edgeFrom;
	vector<GraphEdge*> edgeTo;
	string descriptorPath;

	// Information content
	double odoLikelihood;
	double visLikelihood;
	pair<GraphEdge*,GraphEdge*> bestParents;

	GraphNode(int frameNum, Mat* descriptors, Bagofwords* bagOfWords, string descriptorPath);

	//double updateInformation();

	GraphEdge* addEdgeTo(GraphNode* dest, Vector3d odometry,
			Matrix3d icov);

	// Serialization
	friend class boost::serialization::access;
	template<class Archive>
	void serialize(Archive &ar, const unsigned int version) {

		mexPrintf("SERIALIZATION: Processing GraphNode\n");

		ar & BOOST_SERIALIZATION_NVP(frameNum);
		//ar & BOOST_SERIALIZATION_NVP(position);
		//ar & BOOST_SERIALIZATION_NVP(descriptors);
		//ar & BOOST_SERIALIZATION_NVP(observation);
		ar & BOOST_SERIALIZATION_NVP(descriptorPath);
		ar & BOOST_SERIALIZATION_NVP(edgeFrom);
		ar & BOOST_SERIALIZATION_NVP(edgeTo);
		//ar & BOOST_SERIALIZATION_NVP(odoLikelihood);
		//ar & BOOST_SERIALIZATION_NVP(visLikelihood);
		//ar & BOOST_SERIALIZATION_NVP(bestParents);
	}

};

#endif /* GRAPHNODE_H_ */
